1
|
|
|
/* |
2
|
|
|
backgrid |
3
|
|
|
http://github.com/wyuenho/backgrid |
4
|
|
|
|
5
|
|
|
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors |
6
|
|
|
Licensed under the MIT license. |
7
|
|
|
*/ |
8
|
|
|
describe("A HeaderCell", function () { |
9
|
|
|
|
10
|
|
|
var col; |
11
|
|
|
var cell; |
12
|
|
|
beforeEach(function () { |
13
|
|
|
col = new Backbone.Collection([{ |
14
|
|
|
id: 2 |
15
|
|
|
}, { |
16
|
|
|
id: 1 |
17
|
|
|
}, { |
18
|
|
|
id: 3 |
19
|
|
|
}]); |
20
|
|
|
|
21
|
|
|
cell = new Backgrid.HeaderCell({ |
22
|
|
|
column: { |
23
|
|
|
name: "id", |
24
|
|
|
cell: "integer" |
25
|
|
|
}, |
26
|
|
|
collection: col |
27
|
|
|
}); |
28
|
|
|
|
29
|
|
|
cell.render(); |
30
|
|
|
}); |
31
|
|
|
|
32
|
|
|
it("renders a table header cell with the label text and an optional anchor with sort-caret", function () { |
33
|
|
|
expect(cell.el.tagName).toBe("TH"); |
34
|
|
|
expect(cell.$el.find("button").text()).toBe("id"); |
35
|
|
|
expect(cell.$el.find(".sort-caret").length).toBe(1); |
36
|
|
|
expect(cell.$el.find(".sort-caret").attr("aria-hidden")).toEqual("true"); |
37
|
|
|
|
38
|
|
|
cell.column.set("sortable", false); |
39
|
|
|
cell.render(); |
40
|
|
|
expect(cell.el.tagName).toBe("TH"); |
41
|
|
|
expect(cell.$el.text()).toBe("id"); |
42
|
|
|
expect(cell.$el.find(".sort-caret").length).toBe(0); |
43
|
|
|
}); |
44
|
|
|
|
45
|
|
|
it("adds an editable, sortable and a renderable class to the cell if these column attributes are true", function () { |
46
|
|
|
var column = { |
47
|
|
|
name: "title", |
48
|
|
|
cell: "string" |
49
|
|
|
}; |
50
|
|
|
|
51
|
|
|
cell = new Backgrid.HeaderCell({ |
52
|
|
|
column: column, |
53
|
|
|
collection: col |
54
|
|
|
}); |
55
|
|
|
|
56
|
|
|
expect(cell.$el.hasClass("editable")).toBe(true); |
57
|
|
|
expect(cell.$el.hasClass("sortable")).toBe(true); |
58
|
|
|
expect(cell.$el.hasClass("renderable")).toBe(true); |
59
|
|
|
|
60
|
|
|
cell.column.set("editable", false); |
61
|
|
|
expect(cell.$el.hasClass("editable")).toBe(false); |
62
|
|
|
|
63
|
|
|
cell.column.set("sortable", false); |
64
|
|
|
expect(cell.$el.hasClass("sortable")).toBe(false); |
65
|
|
|
|
66
|
|
|
cell.column.set("renderable", false); |
67
|
|
|
expect(cell.$el.hasClass("renderable")).toBe(false); |
68
|
|
|
|
69
|
|
|
var TrueCol = Backgrid.Column.extend({ |
70
|
|
|
mySortable: function () { |
71
|
|
|
return true; |
72
|
|
|
}, |
73
|
|
|
myRenderable: function () { |
74
|
|
|
return true; |
75
|
|
|
}, |
76
|
|
|
myEditable: function () { |
77
|
|
|
return true; |
78
|
|
|
} |
79
|
|
|
}); |
80
|
|
|
|
81
|
|
|
var FalseCol = Backgrid.Column.extend({ |
82
|
|
|
mySortable: function () { |
83
|
|
|
return false; |
84
|
|
|
}, |
85
|
|
|
myRenderable: function () { |
86
|
|
|
return false; |
87
|
|
|
}, |
88
|
|
|
myEditable: function () { |
89
|
|
|
return false; |
90
|
|
|
} |
91
|
|
|
}); |
92
|
|
|
|
93
|
|
|
column = new TrueCol({ |
94
|
|
|
name: "title", |
95
|
|
|
cell: "string", |
96
|
|
|
sortable: "mySortable", |
97
|
|
|
renderable: "myRenderable", |
98
|
|
|
editable: "myEditable" |
99
|
|
|
}); |
100
|
|
|
|
101
|
|
|
cell = new Backgrid.HeaderCell({ |
102
|
|
|
column: column, |
103
|
|
|
collection: col |
104
|
|
|
}); |
105
|
|
|
|
106
|
|
|
expect(cell.$el.hasClass("editable")).toBe(true); |
107
|
|
|
expect(cell.$el.hasClass("sortable")).toBe(true); |
108
|
|
|
expect(cell.$el.hasClass("renderable")).toBe(true); |
109
|
|
|
|
110
|
|
|
column = new FalseCol({ |
111
|
|
|
name: "title", |
112
|
|
|
cell: "string", |
113
|
|
|
sortable: "mySortable", |
114
|
|
|
renderable: "myRenderable", |
115
|
|
|
editable: "myEditable" |
116
|
|
|
}); |
117
|
|
|
|
118
|
|
|
cell = new Backgrid.HeaderCell({ |
119
|
|
|
column: column, |
120
|
|
|
collection: col |
121
|
|
|
}); |
122
|
|
|
|
123
|
|
|
expect(cell.$el.hasClass("editable")).toBe(false); |
124
|
|
|
expect(cell.$el.hasClass("sortable")).toBe(false); |
125
|
|
|
expect(cell.$el.hasClass("renderable")).toBe(false); |
126
|
|
|
|
127
|
|
|
column = new Backgrid.Column({ |
128
|
|
|
name: "title", |
129
|
|
|
cell: "string", |
130
|
|
|
sortable: function () { |
131
|
|
|
return true; |
132
|
|
|
}, |
133
|
|
|
editable: function () { |
134
|
|
|
return true; |
135
|
|
|
}, |
136
|
|
|
renderable: function () { |
137
|
|
|
return true; |
138
|
|
|
} |
139
|
|
|
}); |
140
|
|
|
|
141
|
|
|
cell = new Backgrid.HeaderCell({ |
142
|
|
|
column: column, |
143
|
|
|
collection: col |
144
|
|
|
}); |
145
|
|
|
|
146
|
|
|
expect(cell.$el.hasClass("editable")).toBe(true); |
147
|
|
|
expect(cell.$el.hasClass("sortable")).toBe(true); |
148
|
|
|
expect(cell.$el.hasClass("renderable")).toBe(true); |
149
|
|
|
}); |
150
|
|
|
|
151
|
|
|
it("will rerender with the column name and/or label changes", function () { |
152
|
|
|
expect(cell.$el.find("button").text(), "id"); |
153
|
|
|
expect(cell.$el.hasClass("id"), true); |
154
|
|
|
|
155
|
|
|
cell.column.set("name", "name"); |
156
|
|
|
expect(cell.$el.find("name"), true); |
157
|
|
|
expect(cell.$el.hasClass("name"), true); |
158
|
|
|
|
159
|
|
|
cell.column.set("label", "Name"); |
160
|
|
|
expect(cell.$el.find("button").text(), "Name"); |
161
|
|
|
expect(cell.$el.hasClass("Name"), true); |
162
|
|
|
}); |
163
|
|
|
|
164
|
|
|
it("will put a class indicating the sorting direction if `direction` is set in the column", function () { |
165
|
|
|
cell = new Backgrid.HeaderCell({ |
166
|
|
|
column: { |
167
|
|
|
name: "id", |
168
|
|
|
cell: "integer", |
169
|
|
|
direction: "descending" |
170
|
|
|
}, |
171
|
|
|
collection: col |
172
|
|
|
}); |
173
|
|
|
|
174
|
|
|
cell.render(); |
175
|
|
|
|
176
|
|
|
expect(cell.el.tagName).toBe("TH"); |
177
|
|
|
expect(cell.$el.find("button").text()).toBe("id"); |
178
|
|
|
expect(cell.$el.find(".sort-caret").length).toBe(1); |
179
|
|
|
expect(cell.$el.hasClass("descending")).toBe(true); |
180
|
|
|
}); |
181
|
|
|
|
182
|
|
|
it("triggers `backgrid:sort` with the column and direction set to 'ascending' if the column's direction is not set", function () { |
183
|
|
|
var column, direction; |
184
|
|
|
cell.collection.on("backgrid:sort", function (col, dir) { |
185
|
|
|
column = col; |
186
|
|
|
direction = dir; |
187
|
|
|
}); |
188
|
|
|
cell.$el.find("button").click(); |
189
|
|
|
expect(column).toBe(cell.column); |
190
|
|
|
expect(direction).toBe("ascending"); |
191
|
|
|
}); |
192
|
|
|
|
193
|
|
|
it("triggers `backgrid:sort` with the column and direction set to 'descending' if the column's direction is set to 'ascending'", function () { |
194
|
|
|
var column, direction; |
195
|
|
|
cell.collection.on("backgrid:sort", function (col, dir) { |
196
|
|
|
column = col; |
197
|
|
|
direction = dir; |
198
|
|
|
}); |
199
|
|
|
cell.column.set("direction", "ascending"); |
200
|
|
|
cell.$el.find("button").click(); |
201
|
|
|
expect(column).toBe(cell.column); |
202
|
|
|
expect(direction).toBe("descending"); |
203
|
|
|
}); |
204
|
|
|
|
205
|
|
|
it("triggers `backgrid:sort` with the column and direction set to `null` if the column's direction is set to 'descending'", function () { |
206
|
|
|
var column, direction; |
207
|
|
|
cell.collection.on("backgrid:sort", function (col, dir) { |
208
|
|
|
column = col; |
209
|
|
|
direction = dir; |
210
|
|
|
}); |
211
|
|
|
cell.column.set("direction", "descending"); |
212
|
|
|
cell.$el.find("button").click(); |
213
|
|
|
expect(column).toBe(cell.column); |
214
|
|
|
expect(direction).toBeNull(); |
215
|
|
|
}); |
216
|
|
|
|
217
|
|
|
it("will set the column to the correct direction when `change:direction` is triggered from the column", function () { |
218
|
|
|
cell.column.set("direction", "ascending"); |
219
|
|
|
expect(cell.$el.hasClass("ascending")).toBe(true); |
220
|
|
|
cell.column.set("direction", "descending"); |
221
|
|
|
expect(cell.$el.hasClass("descending")).toBe(true); |
222
|
|
|
cell.column.set("direction", null); |
223
|
|
|
expect(cell.$el.hasClass("ascending")).toBe(false); |
224
|
|
|
expect(cell.$el.hasClass("descending")).toBe(false); |
225
|
|
|
}); |
226
|
|
|
|
227
|
|
|
it("will remove its direction CSS class if `backgrid:sorted` is triggered from the collection or pageableCollection#fullCollection", function () { |
228
|
|
|
cell.column.set("direction", "ascending"); |
229
|
|
|
expect(cell.$el.hasClass("ascending")).toBe(true); |
230
|
|
|
cell.collection.comparator = "id"; |
231
|
|
|
cell.collection.sort(); |
232
|
|
|
cell.collection.trigger("backgrid:sorted"); |
233
|
|
|
expect(cell.$el.hasClass("ascending")).toBe(false); |
234
|
|
|
expect(cell.$el.hasClass("descending")).toBe(false); |
235
|
|
|
|
236
|
|
|
col = new Backbone.PageableCollection(col.toJSON(), { |
237
|
|
|
mode: "client" |
238
|
|
|
}); |
239
|
|
|
col.setSorting("id", 1); |
240
|
|
|
cell = new Backgrid.HeaderCell({ |
241
|
|
|
column: { |
242
|
|
|
name: "id", |
243
|
|
|
cell: "integer" |
244
|
|
|
}, |
245
|
|
|
collection: col |
246
|
|
|
}); |
247
|
|
|
|
248
|
|
|
cell.column.set("direction", "ascending"); |
249
|
|
|
expect(cell.$el.hasClass("ascending")).toBe(true); |
250
|
|
|
cell.collection.fullCollection.comparator = "id"; |
251
|
|
|
cell.collection.fullCollection.sort(); |
252
|
|
|
cell.collection.fullCollection.trigger("backgrid:sorted"); |
253
|
|
|
expect(cell.$el.hasClass("ascending")).toBe(false); |
254
|
|
|
expect(cell.$el.hasClass("descending")).toBe(false); |
255
|
|
|
}); |
256
|
|
|
|
257
|
|
|
it("with `sortType` set to `toggle`, triggers `backgrid:sort` with the column and direction set to 'ascending' if the column's direction is not set", function () { |
258
|
|
|
var column, direction; |
259
|
|
|
cell.column.set("sortType", "toggle"); |
260
|
|
|
cell.collection.on("backgrid:sort", function (col, dir) { |
261
|
|
|
column = col; |
262
|
|
|
direction = dir; |
263
|
|
|
}); |
264
|
|
|
cell.$el.find("button").click(); |
265
|
|
|
expect(column).toBe(cell.column); |
266
|
|
|
expect(direction).toBe("ascending"); |
267
|
|
|
}); |
268
|
|
|
|
269
|
|
|
it("with `sortType` set to `toggle`, triggers `backgrid:sort` with the column and direction set to 'descending' if the column's direction is set to 'ascending'", function () { |
270
|
|
|
var column, direction; |
271
|
|
|
cell.column.set("sortType", "toggle"); |
272
|
|
|
cell.column.set("direction", "ascending"); |
273
|
|
|
cell.collection.on("backgrid:sort", function (col, dir) { |
274
|
|
|
column = col; |
275
|
|
|
direction = dir; |
276
|
|
|
}); |
277
|
|
|
cell.$el.find("button").click(); |
278
|
|
|
expect(column).toBe(cell.column); |
279
|
|
|
expect(direction).toBe("descending"); |
280
|
|
|
}); |
281
|
|
|
|
282
|
|
|
it("with `sortType` set to `toggle`, triggers `backgrid:sort` with the column and direction set to 'ascending' if the column's direction is set to 'descending'", function () { |
283
|
|
|
var column, direction; |
284
|
|
|
cell.column.set("sortType", "toggle"); |
285
|
|
|
cell.column.set("direction", "descending"); |
286
|
|
|
cell.collection.on("backgrid:sort", function (col, dir) { |
287
|
|
|
column = col; |
288
|
|
|
direction = dir; |
289
|
|
|
}); |
290
|
|
|
cell.$el.find("button").click(); |
291
|
|
|
expect(column).toBe(cell.column); |
292
|
|
|
expect(direction).toBe("ascending"); |
293
|
|
|
}); |
294
|
|
|
|
295
|
|
|
}); |
296
|
|
|
|
297
|
|
|
describe("A HeaderRow", function () { |
298
|
|
|
|
299
|
|
|
var Book = Backbone.Model.extend({}); |
300
|
|
|
|
301
|
|
|
var Books = Backbone.Collection.extend({ |
302
|
|
|
model: Book |
303
|
|
|
}); |
304
|
|
|
|
305
|
|
|
var books; |
306
|
|
|
var row; |
307
|
|
|
|
308
|
|
|
beforeEach(function () { |
309
|
|
|
|
310
|
|
|
books = new Books([{ |
311
|
|
|
title: "Alice's Adventures in Wonderland", |
312
|
|
|
year: 1865 |
313
|
|
|
}, { |
314
|
|
|
title: "A Tale of Two Cities", |
315
|
|
|
year: 1859 |
316
|
|
|
}, { |
317
|
|
|
title: "The Catcher in the Rye", |
318
|
|
|
year: 1951 |
319
|
|
|
}]); |
320
|
|
|
|
321
|
|
|
row = new Backgrid.HeaderRow({ |
322
|
|
|
columns: [{ |
323
|
|
|
name: "name", |
324
|
|
|
cell: "string" |
325
|
|
|
}, { |
326
|
|
|
name: "year", |
327
|
|
|
cell: "integer" |
328
|
|
|
}], |
329
|
|
|
collection: books |
330
|
|
|
}); |
331
|
|
|
|
332
|
|
|
row.render(); |
333
|
|
|
}); |
334
|
|
|
|
335
|
|
|
it("renders a row of header cells", function () { |
336
|
|
|
expect(row.$el[0].tagName).toBe("TR"); |
337
|
|
|
var th1 = $(row.el.childNodes[0]); |
338
|
|
|
expect(th1.hasClass("editable")).toBe(true); |
339
|
|
|
expect(th1.hasClass("sortable")).toBe(true); |
340
|
|
|
expect(th1.hasClass("renderable")).toBe(true); |
341
|
|
|
expect(th1.hasClass("name")).toBe(true); |
342
|
|
|
expect(th1.find("button").text()).toBe("name"); |
343
|
|
|
expect(th1.find("button").eq(1).is($("b", { |
344
|
|
|
className: "sort-caret" |
345
|
|
|
}))); |
346
|
|
|
|
347
|
|
|
var th2 = $(row.el.childNodes[1]); |
348
|
|
|
expect(th2.hasClass("editable")).toBe(true); |
349
|
|
|
expect(th2.hasClass("sortable")).toBe(true); |
350
|
|
|
expect(th2.hasClass("renderable")).toBe(true); |
351
|
|
|
expect(th2.hasClass("year")).toBe(true); |
352
|
|
|
expect(th2.find("button").text()).toBe("year"); |
353
|
|
|
expect(th2.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true); |
354
|
|
|
}); |
355
|
|
|
|
356
|
|
|
it("resets the carets of the non-sorting columns", function () { |
357
|
|
|
row.$el.find("button").eq(0).click(); // ascending |
358
|
|
|
row.$el.find("button").eq(1).click(); // ascending, resets the previous |
359
|
|
|
expect(row.$el.find("button").eq(0).hasClass("ascending")).toBe(false); |
360
|
|
|
expect(row.$el.find("button").eq(1).hasClass("ascending")).toBe(false); |
361
|
|
|
}); |
362
|
|
|
|
363
|
|
|
it("inserts or removes a cell if a column is added or removed", function () { |
364
|
|
|
row.columns.add({ |
365
|
|
|
name: "price", |
366
|
|
|
cell: "number" |
367
|
|
|
}); |
368
|
|
|
expect(row.$el.children().length).toBe(3); |
369
|
|
|
var lastTh = $(row.el.lastChild); |
370
|
|
|
expect(lastTh.hasClass("editable")).toBe(true); |
371
|
|
|
expect(lastTh.hasClass("sortable")).toBe(true); |
372
|
|
|
expect(lastTh.hasClass("renderable")).toBe(true); |
373
|
|
|
expect(lastTh.hasClass("price")).toBe(true); |
374
|
|
|
expect(lastTh.find("button").text()).toBe("price"); |
375
|
|
|
expect(lastTh.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true); |
376
|
|
|
|
377
|
|
|
row.columns.add({ |
378
|
|
|
name: "publisher", |
379
|
|
|
cell: "string", |
380
|
|
|
renderable: false |
381
|
|
|
}); |
382
|
|
|
expect(row.$el.children().length).toBe(4); |
383
|
|
|
expect(row.$el.children().last().find("button").text()).toBe("publisher"); |
384
|
|
|
expect(row.$el.children().last().hasClass("renderable")).toBe(false); |
385
|
|
|
|
386
|
|
|
row.columns.remove(row.columns.first()); |
387
|
|
|
expect(row.$el.children().length).toBe(3); |
388
|
|
|
var firstTh = $(row.el.firstChild); |
389
|
|
|
expect(firstTh.hasClass("editable")).toBe(true); |
390
|
|
|
expect(firstTh.hasClass("sortable")).toBe(true); |
391
|
|
|
expect(firstTh.hasClass("renderable")).toBe(true); |
392
|
|
|
expect(firstTh.hasClass("year")).toBe(true); |
393
|
|
|
expect(firstTh.find("button").text()).toBe("year"); |
394
|
|
|
expect(firstTh.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true); |
395
|
|
|
}); |
396
|
|
|
|
397
|
|
|
}); |
398
|
|
|
|
399
|
|
|
describe("A Header", function () { |
400
|
|
|
|
401
|
|
|
var Book = Backbone.Model.extend({}); |
402
|
|
|
|
403
|
|
|
var Books = Backbone.Collection.extend({ |
404
|
|
|
model: Book |
405
|
|
|
}); |
406
|
|
|
|
407
|
|
|
var books; |
408
|
|
|
var head; |
409
|
|
|
|
410
|
|
|
beforeEach(function () { |
411
|
|
|
|
412
|
|
|
books = new Books([{ |
413
|
|
|
title: "Alice's Adventures in Wonderland", |
414
|
|
|
year: 1865 |
415
|
|
|
}, { |
416
|
|
|
title: "A Tale of Two Cities", |
417
|
|
|
year: 1859 |
418
|
|
|
}, { |
419
|
|
|
title: "The Catcher in the Rye", |
420
|
|
|
year: 1951 |
421
|
|
|
}]); |
422
|
|
|
|
423
|
|
|
head = new Backgrid.Header({ |
424
|
|
|
columns: [{ |
425
|
|
|
name: "name", |
426
|
|
|
cell: "string" |
427
|
|
|
}, { |
428
|
|
|
name: "year", |
429
|
|
|
cell: "integer" |
430
|
|
|
}], |
431
|
|
|
collection: books |
432
|
|
|
}); |
433
|
|
|
|
434
|
|
|
head.render(); |
435
|
|
|
}); |
436
|
|
|
|
437
|
|
|
it("renders a header with a row of header cells", function () { |
438
|
|
|
expect(head.$el[0].tagName).toBe("THEAD"); |
439
|
|
|
|
440
|
|
|
var th1 = $(head.row.el.childNodes[0]); |
441
|
|
|
expect(th1.hasClass("editable")).toBe(true); |
442
|
|
|
expect(th1.hasClass("sortable")).toBe(true); |
443
|
|
|
expect(th1.hasClass("renderable")).toBe(true); |
444
|
|
|
expect(th1.hasClass("name")).toBe(true); |
445
|
|
|
expect(th1.find("button").text()).toBe("name"); |
446
|
|
|
expect(th1.find("button").eq(1).is($("b", { |
447
|
|
|
className: "sort-caret" |
448
|
|
|
}))); |
449
|
|
|
|
450
|
|
|
var th2 = $(head.row.el.childNodes[1]); |
451
|
|
|
expect(th2.hasClass("editable")).toBe(true); |
452
|
|
|
expect(th2.hasClass("sortable")).toBe(true); |
453
|
|
|
expect(th2.hasClass("renderable")).toBe(true); |
454
|
|
|
expect(th2.hasClass("year")).toBe(true); |
455
|
|
|
expect(th2.find("button").text()).toBe("year"); |
456
|
|
|
expect(th2.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true); |
457
|
|
|
}); |
458
|
|
|
|
459
|
|
|
}); |
460
|
|
|
|